import Code from "components/Markdown/Code"

export const meta = {
  title: "Prisma & Mongoose",
  position: 80,
  description: "Learn how Prisma compares to Mongoose"
}

## Reading data

### Fetching single objects

Mongoose

```ts
const user = await findById(id)
```

Prisma

```ts
const user = await prisma.user({ id })
```

### Fetching selected scalars of single objects

Mongoose

```ts
const user = await findById(id)
  .select("id email")
```

Prisma

```ts
const userFragment = await prisma.user({ id }).$fragment(`
  fragment NameAndEmail on User { id email }`
`)
```

### Fetching relations

Mongoose

```ts
const userWithPosts = await User
  .findById(id)
  .populate("posts")
```

Prisma

<Code languages={["Fluent API", "Using fragments", "Native GraphQL"]}>

```ts
const postsByUser = await prisma
  .user({ id })
  .posts()
```

```ts
const userWithPosts = await prisma
  .user({ id })
  .$fragment(`
    fragment UserPosts on User {
      posts { id title content published }
    }
  `)
```

```ts
const userWithPosts = await prisma
  .$graphql(`
    query ($id: ID!) {
      user(id: $id) {
        posts { id title content published }
      }
    }
  `, 
  { id }
  )
```

</Code>

### Filtering for concrete values

Mongoose

```ts
const user = await User.find({
  name: "Alice"
})
```

Prisma

```ts
const user = await prisma.users({
  where: {
    name: "Alice"
  }
})
```

### Other filter criteria

Mongoose

Mongoose exposes the [MongoDB query selectors](https://docs.mongodb.com/manual/reference/operator/query/#query-selectors) as filter criteria.

Prisma

Prisma generates many additional filters that are commonly used in modern application development:

- `<field>_ends_with` & `<field>_starts_with`
- `<field>_not_ends_with` & `<field>_not_starts_with`
- `<field>_gt` & `<field>_gte`
- `<field>_lt` & `<field>_lte`
- `<field>_contains` & `<field>_not_contains`
- `<field>_in` & `<field>_not_in`

### Relation filters

Mongoose

Mongoose doesn't offer a dedicated API for relation filters. You can get similar functionality by sending a raw SQL query to the database.

Prisma

Prisma lets you filter a list based on a criteria that applies not only to the models of the list being retrieved, but to a _relation_ of that model. 

For example, you want to fetch only those users that wrote a post with the title "Hello World". The filter criteria is therefore not referencing the user model, but the post model that's related to the user model:

```ts
query {
  user(where: {
    posts_some: {
      title: "Hello World"
    }
  }) {
    id
  }
}
```

### Pagination

Mongoose

```ts
const posts = await Post.find({
  skip: 5,
  limit: 10
})
```

Prisma

```ts
const posts = await prisma.posts({
  skip: 5,
  first: 10
})
```

In addition to `skip` and `first`, the Prisma API also offers:

- `last`
- `before` & `after` for cursor based pagination
- Relay-style pagination

## Writing data

### Creating objects

Mongoose

<Code languages={["Using `create`", "Using `save`"]}>

```ts
const user = await User.create({
  name: "Alice",
  email: "alice@prisma.io"
})
```

```ts
const user = new User({
  name: "Alice",
  email: "alice@prisma.io"
})
await user.save()
```

</Code>

Prisma

```ts
const user = await new User({
  name: "Alice",
  email: "alice@prisma.io"
})
```

### Updating objects

Mongoose

<Code languages={["Using `findOneAndUpdate`", "Using `save`"]}>

```ts
const updatedUser = await User.findOneAndUpdate(
  { _id: id },
  {
    $set: {
      name: "James",
      email: "james@prisma.io"
    }
  }
)
```

```ts
user.name = "James"
user.email =" james@prisma.com"
await user.save()
```

</Code>

Prisma

```ts
const updatedUser = await prisma.updateUser({
  where: { id },
  data: {
    name: "James",
    email: "james@prisma.io"
  }
})
```

### Deleting objects

Mongoose

```ts
await User.deleteOne({ _id: id })
```

Prisma

```ts
const deletedUser = await prisma.deleteUser({ id })
```
